package mathtools;

import mathtools.Complex;

/**
 * Represents a complex number with real and imaginary components.
 * Includes classes for all needed complex number algebra.
 * @author Alex Bush, Richard Inskip, Jan Zaucha
 */
public class Complex {

	/** Real component of the complex number */
	protected float x;
	/** Imaginary component of the complex number */
	protected float y;

	/**
	 * Create a complex number with real and imaginary components 
	 * @param x real coefficient
	 * @param y imaginary coefficient
	 */
	public Complex (float x, float y) {
		this.x = x;
		this.y = y;
	}

	/**
	 * Create a complex purely real number
	 * imaginary part = 0
	 * @param x real coefficient
	 */
	public Complex (float x) {
		this.x = x;
		this.y = 0.0f;
	}

	/** Set real component
	 * 
	 * @param x value to set real component
	 */
	public void setReal(float x) {
		this.x = x;
	}


	/** Set imaginary component of the complex number
	 * 
	 * @param y value to set imaginary component
	 */
	public void setImaginary(float y) {
		this.y = y;
	}

	/**
	 * Returns real component of the complex number
	 * @return Real component
	 */
	public float getReal (){
		return this.x;
	}

	/**
	 * Returns imaginary component of the complex number
	 * @return Imaginary component
	 */
	public float getImaginary (){
		return this.y;
	}

	/**
	 * Return magnitude of the complex number <code>sqrt(x^2 + y^2)</code>
	 * @return Magnitude of the complex number
	 */
	public Double getMagnitude (){
		double mag = Math.sqrt(this.x * this.x + this.y * this.y);
		return mag;
	}

	/**
	 * Return the square magnitude of the complex number <code>x^2+y^2</code>
	 * @return Square Magnitude of the complex number
	 */
	public Double getMagnitudeSquared (){
		double mag = (this.x * this.x + this.y * this.y);
		return mag;
	}

	/**
	 * Return the complex number as a string
	 * @return Complex number
	 */
	public String toString (){
		if ( y==0 ){
			return this.x+"";
		}
		else if ( x==0 ){
			return this.y+"i";
		}
		else{
			return "(" + this.x + " + " + this.y + "i" + ")";
		}
	}

	/**
	 * Static method to add two complex numbers together
	 * @param a First Complex number
	 * @param b Second Complex number
	 * @return Complex number a + Complex Number b
	 */
	public static Complex addComplex (Complex a, Complex b) {
		Complex c = new Complex(a.getReal() + b.getReal(), a.getImaginary() + b.getImaginary());
		return c;
	}

	/**
	 * Static method to multiply two complex numbers togther
	 * @param a First Complex Number
	 * @param b Second Complex Number
	 * @return Complex number a x Complex Number b
	 */
	public static Complex multiplyComplex (Complex a, Complex b) {
		Complex c = new Complex (a.getReal()*b.getReal() - a.getImaginary() * b.getImaginary(), a.getReal() * b.getImaginary() + a.getImaginary() * b.getReal());
		return c;
	}

	/**
	 * Static method to multiply a complex number by a real number
	 * @param a A Real number
	 * @param b A complex number
	 * @return Complex number C = a * ( Complex b )
	 */
	public static Complex multiplyComplex (float a, Complex b ) {
		Complex c = new Complex (a * b.getReal(), a * b.getImaginary());
		return c;
	}

	/**
	 * Method to multiply the complex number by -1.0; real -> -real , im -> -im.
	 */
	public void negate (){
		x = -x;
		y = -y;
	}

	/**
	 * Return the complex conjugate of an imaginary number
	 * @return Complex conjugate of complex number
	 */
	public Complex conjugate(){
		return new Complex(x,(-1)*y);
	}

}